function [ d_d] = WiSiL_Decoder_rateMatching(softOutput,rateMatching,HARQ,harqParams)

% This function receives the soft output of the demodulator and
% prepares it to be decoded by the turbo decoder.
%
% Inputs:
% softOutput: it is a cell array containing the corresponding soft values 
% of the rate matched bits
%
% rateMatching: it is a structure containing information related to the 
% rate matching process done at the encoder.
%
% HARQ: structure that storages the ACK/NACK and number of repetitions 
% concerning the HARQ protocol  
%
% harqParams: structure containing information about the type of HARQ that
% will be performed.
%
% Outputs:
% d_d: it is a cell array that contains the the received bits arranged 
% This function undoes all the steps made at the encoder's rate matching 
% process: recreates the circular buffer, recreates the outputs of the rate
% matching's interleaver and etc.
%
% The punctured bits are replaced by '0' in accordance with the soft output
% logic. As a result, no changes need to be made at the turbo decoder.
% To properly recreate the circular buffer we need to perform again 
% the following rate matching stages on a dummy vector of zeros:
% interleaving and bit collection at the circular buffer.
%
% This is needed because we need to know exactly where in the circular
% buffer each bit (or soft output) originally was before the bit collection
% process. Since the bit collection process eliminates the dummy NaN
% elements we find out where they were by recreating the two initial rate
% matching steps.

% History:
%
%   Lucas Sousa e Silva 08/2014 - created


%--------------------------------------------------------------------------
% Useful parameters.


P = [1,17,9,25,5,21,13,29,3,19,11,27,7,23,15,31,2,18,10,26,6,22,14,30,4,...
    20,12,28,8,24,16,32];
C_subBlock = 32;                                                            % Number of columns.
k0 = rateMatching.k0;
d_d = cell(length(softOutput),1);                                           % Array Initialization 
% Recreating the circular buffer with the dummy bits (nan). 

for r = 1:length(softOutput)
    
    if(strcmpi(harqParams.combination,'CC')==1)
        rep = 1;
    else
        rep = HARQ.repetitions(r);
    end
    
    N_cb = rateMatching.N_cb(r);
    D = rateMatching.D(r);                                                  % Length of the bitstream.
    R_subBlock = ceil(D/C_subBlock);                                        % Number of rows.
    N_D = R_subBlock*C_subBlock - D;                                        % Number of dummy bits.
    E = size(softOutput{r,1},2);                                            % Length of the transmitted vector.
    v_d = zeros(3,C_subBlock*R_subBlock);                                   %initialization of matrix v.

    % Interleaving.

    for t = 1:3
        y_d = [nan(1,N_D) zeros(1,D)];                                      % Dummy bits(nan)are inserted at the beggining of the bitstream.
        if (t < 3)
            Y_d = vec2mat(y_d,C_subBlock);                                  % Writes the bitstream into a matrix R_subBlock X C_subBlock.
            Y_pd = Y_d(:,P);                                                % Permutes the columns according to vector P.
            v_d(t,:) = Y_pd(:)';                                            % Output of the interleaver.
        else
            for k = 0:length(y_d)-1
                v_d(t,k+1) = y_d(mod((P(floor(k/R_subBlock)+1)+ C_subBlock*mod(k,R_subBlock)+1),length(y_d))+1);
            end
        end
    end

    % Bit collection in circular Buffer.
    k_w = 3*size(v_d,2);
    w_d = zeros(1,k_w);
    w_d(1:size(v_d,2)) = v_d(1,:);
    w_d(size(v_d,2)+1:2:end) = v_d(2,:);
    w_d(size(v_d,2)+2:2:end) = v_d(3,:);

    % Inserting the received bitstream into the circular buffer

    for t = 1:rep
        k = 0;
        u = 0;

        while (k < E)
            if (isnan(w_d(mod((k0(r,t)+u),N_cb)+1)) == 0)
                w_d(mod((k0(r,t)+u),N_cb)+1) = w_d(mod((k0(r,t)+u),N_cb)+1) + softOutput{r}(t,k+1);
                k = k + 1;
            end
            u = u + 1;
        end
    end

    % Recreating the outputs of the inteleaver.
    v_d(1,:) = w_d(1:k_w/3);
    v_d(2,:) = w_d(k_w/3 + 1:2:end);
    v_d(3,:) = w_d(k_w/3 + 2:2:end);

    % Recreating the inputs of the intervleaver.

    for t = 1:3
        if (t < 3)
            Y_pd = reshape(v_d(t,:),R_subBlock,C_subBlock);
            Y_d = Y_pd(:,P); % Permutes the columns according to vector P.
            Y_d = Y_d';
            y_d(t,:) = Y_d(:)';
        else
            for k = 0:length(v_d(t,:))-1
                y_d(t,mod((P(floor(k/R_subBlock)+1)+ ...
                C_subBlock*mod(k,R_subBlock)+1),length(v_d(t,:)))+1)= v_d(t,k+1);
            end
        end
    end
    d_d{r} = y_d(:,N_D +1:1:end);  %eliminates the dummy bits
    if (r == 1)
        d_d{r} = [nan(3,rateMatching.fillerBits) d_d{r}];       % Add filler bits to the 1st code block 
    end
end
